﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using JTest.BUS;
using JTest.Others;
using System.Threading;
using System.Collections;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using JTest.DTO;

namespace JTest.GUI
{
    /// <summary>
    /// @Author LuongGV
    /// </summary>
    public partial class frmImportDB : Form
    {
        private frmWait waitForm;

        public frmImportDB()
        {
            InitializeComponent();
            waitForm = new frmWait(this);
            bkWorker.WorkerReportsProgress = true;
        }



        private void btnApply_Click(object sender, EventArgs e)
        {
            // dic obj store param pass to bkworker.doWork
            Dictionary<string, object> args = new Dictionary<string, object>();

            int level = (int)Enum.Parse(typeof(EnumLevel), cmbLevel.SelectedValue.ToString());
            string type = cmbType.SelectedValue.ToString();
            string filePath = txtFilePath.Text;

            // Validate
            if (filePath.Length == 0)
            {
                MessageBox.Show("Vui lòng chọn đường dẫn tập tin dữ liệu.", "Yêu cầu", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            if (rdNew.Checked == true &&
                (txtName.Text.Length == 0 || !(Regex.IsMatch(txtName.Text, "^[a-zA-Z0-9_]{4,25}$"))))
            {
                MessageBox.Show("Vui lòng nhập tên CSDL từ 4 đến 25 ký tự với các kí tự hợp lệ [A-Za-z0-9_].", "Yêu cầu", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                txtName.Text = "";
                txtName.Focus();
                return;
            }

            args.Add("level", level);
            args.Add("type", type);
            args.Add("filePath", filePath);

            if (rdExpand.Checked)
            {
                string db = cmbDbName.SelectedValue.ToString();
                args.Add("action", "insert");
                args.Add("db", db);

            }
            else if (rdNew.Checked)
            {
                string db = txtName.Text;
                args.Add("action", "new");
                args.Add("db", db);
            }

            // Display wait form
            if (waitForm.IsDisposed != false)
            {
                waitForm = new frmWait(this);
            }
            // center alignment
            waitForm.TopLevel = false;
            waitForm.Parent = this;
            waitForm.StartPosition = FormStartPosition.CenterParent;
            waitForm.Top = (this.Height - waitForm.Height) / 2;
            waitForm.Left = (this.Width - waitForm.Width) / 2;
            waitForm.Show();
            waitForm.BringToFront();
            pnlContainer.Enabled = false;

            bkWorker.RunWorkerAsync(args);

        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnOpenFile_Click(object sender, EventArgs e)
        {
            if (ofdSource.ShowDialog() == DialogResult.OK)
            {
                txtFilePath.Text = ofdSource.FileName;
            }
        }

        private void frmImportDB_Load(object sender, EventArgs e)
        {
            // populate level and type datasource from enums
            cmbDbName.Items.Clear();
            cmbLevel.DataSource = EnumHelper.ToList(typeof(EnumLevel));
            cmbLevel.DisplayMember = "Key";
            cmbLevel.ValueMember = "Value";

            cmbType.Items.Clear();
            cmbType.DataSource = EnumHelper.ToList(typeof(EnumType));
            cmbType.DisplayMember = "Key";
            cmbType.ValueMember = "Value";

            cmbDbName.DataSource = SettingsBUS.loadDbaseSources();
            cmbDbName.SelectedIndex = 0;
        }

        /// <summary>
        /// Handles the DoWork event of the bkWorker control.
        /// Call DataImportBUS to insert or create new database
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
        private void bkWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            Dictionary<string, object> agrs = (Dictionary<string, object>)e.Argument;
            string action = agrs["action"].ToString();
            string filePath = agrs["filePath"].ToString();
            string db = agrs["db"].ToString();
            string type = agrs["type"].ToString();
            int level = Int32.Parse(agrs["level"].ToString());
            StringBuilder builder = new StringBuilder();

            try
            {
                // load data in file
                List<QuestionDTO> list = DataImportBUS.getQuestionListFromExcel(filePath);
                if (list.Count == 0)
                {
                    throw new Exception("Không tìm thấy câu hỏi trong tập tin. Vui lòng kiểm tra lại định dạng tập tin.");
                }

                // Perform 
                if (action.Equals("insert"))
                {
                    // perform insert
                    int total = DataImportBUS.insertData(list, db, type, level);

                    // report to wait dialog
                    bkWorker.ReportProgress(100);

                    // Information to display
                    builder.AppendLine("Phương pháp : Thêm dữ liệu");
                    builder.AppendLine("CSDL : " + db);
                    builder.AppendLine("Loại : " + EnumHelper.getDescription((Enum)Enum.Parse(typeof(EnumType), type)));
                    builder.AppendLine("Cấp độ : N" + level);
                    builder.AppendLine("Tổng số câu: " + total);
                    // return result
                    e.Result = builder.ToString();
                }
                else if (action.Equals("new"))
                {
                    // create new db 
                    string dbName = DataImportBUS.createNewDbase(db);
                    // perform insert
                    int total = DataImportBUS.insertData(list, dbName, type, level);

                    // report to wait dialog
                    bkWorker.ReportProgress(100);
                    Thread.Sleep(500);

                    // Information to Display
                    builder.AppendLine("Phương pháp : Tạo CSDL mới");
                    builder.AppendLine("CSDL : " + db);
                    builder.AppendLine("Loại : " + EnumHelper.getDescription((Enum)Enum.Parse(typeof(EnumType), type)));
                    builder.AppendLine("Cấp độ : N" + level);
                    builder.AppendLine("Tổng số câu: " + total);
                    // return result
                    e.Result = builder.ToString();
                }
            }
            catch (Exception ex)
            {
                bkWorker.ReportProgress(50);
                e.Result = "failed";
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error,MessageBoxDefaultButton.Button1);
            }
        }

        /// <summary>
        /// Handles the RunWorkerCompleted event of the bkWorker control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event data.</param>
        private void bkWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            waitForm.Close();
            if (!e.Result.ToString().Equals("failed"))
            {
                MessageBox.Show(e.Result.ToString(), "Thông tin", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            resetControls();
            pnlContainer.Enabled = true;
        }

        /// <summary>
        /// Handles the CheckedChanged event of the rdExpand control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void rdExpand_CheckedChanged(object sender, EventArgs e)
        {
            if (cmbDbName.Enabled == false)
            {
                lblForCSDL.Enabled = true;
                cmbDbName.Enabled = true;
                txtName.Enabled = false;
                lblForName.Enabled = false;
            }
        }

        /// <summary>
        /// Handles the CheckedChanged event of the rdNew control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void rdNew_CheckedChanged(object sender, EventArgs e)
        {
            if (txtName.Enabled == false)
            {
                lblForName.Enabled = true;
                txtName.Enabled = true;
                cmbDbName.Enabled = false;
                lblForCSDL.Enabled = false;
            }
        }

        /// <summary>
        /// Resets the controls to default.
        /// </summary>
        private void resetControls()
        {
            // populate level and type datasource from enums
            cmbLevel.DataSource = EnumHelper.ToList(typeof(EnumLevel));
            cmbLevel.DisplayMember = "Key";
            cmbLevel.ValueMember = "Value";

            cmbType.DataSource = EnumHelper.ToList(typeof(EnumType));
            cmbType.DisplayMember = "Key";
            cmbType.ValueMember = "Value";

            cmbDbName.DataSource = SettingsBUS.loadDbaseSources();
            cmbDbName.SelectedIndex = 0;

            txtName.Text = "";
            txtFilePath.Text = "";

            rdExpand.Checked = true;
        }

        /// <summary>
        /// Handles the ProgressChanged event of the bkWorker control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.ProgressChangedEventArgs"/> instance containing the event data.</param>
        private void bkWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage < 100)
            {
                waitForm.InfoText = "Thất bại.";
            }
            else
            {
                waitForm.InfoText = "Hoàn thành.";
            }
        }

    }
}
